home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Mac Format 1994 October
/
Macformat17.cdr
/
Shareware City
/
Developers
/
xlispmac
/
src
/
macint.c
< prev
next >
Wrap
Text File
|
1994-06-25
|
30KB
|
982 lines
/* macint.c - macintosh interface routines for xlisp 2.1e */
/* Written by Brian Kendig. */
/* The functions here are only called by macstuff.c. */
#include <THINK.h>
#include <Desk.h>
#include <Events.h>
#include <GestaltEQU.h>
#include <LoMem.h>
#include <Memory.h>
#include <Menus.h>
#include <OSEvents.h>
#include <Quickdraw.h>
#include <StandardFile.h>
#include <TextEdit.h>
#include <ToolUtils.h>
#include <Traps.h>
#include <Windows.h>
#include <pascal.h>
#include "macint.h"
#define TEXTREC (*hTERec) /* the command window text record */
#define TEXTCHAR(i) ((*(TEXTREC->hText))[i])
MenuHandle appleMenu, fileMenu, editMenu, controlMenu;
/* command and graphics windows */
WindowPtr commandWin, graphicsWin;
WindowRecord commandWinRec, bwGraphicsWinRec;
CWindowRecord colorGraphicsWinRec;
Boolean graphicsShown, commandWinResized = false;
Rect dragRect, sizeRect;
int screenWidth, screenHeight; /* screen dimensions */
int sHorizontal, sVertical, sWidth, sHeight; /* command win, split screen */
int gHorizontal, gVertical, gWidth, gHeight; /* graphics win, split screen */
/* output is buffered */
Handle hOutputBuffer = NULL;
int outputBufferLength = 0;
/* miscellaneous stuff */
char recentChar; /* the last character typed */
int cursorPos; /* the cursor's position on the line */
short linesInView; /* how many lines are in the window */
CharsHandle pastedTextH = NULL; /* a handle to pasted text */
int pastedLength = 0; /* how many chars there are in the paste buffer */
int flashTime = 0, cursorBeforeFlash; /* for flashing cursor when parens match */
int cmdStart; /* where (in text record) the current command starts */
TextStyle textStyle[2]; /* styles: bold for user input, plain for output */
enum { plainStyle, boldStyle } currentStyle;
int wneImplemented;
EventRecord theEvent;
TEHandle hTERec;
ControlHandle vScroll;
unsigned long startupTicks;
Boolean hasColorQD;
short howManyFiles = 0, whichFile = 0; /* keep track of files opened from Finder */
void DoEvent (void); /* forward */
void FlushOutput (void); /* forward */
static void DoScrollBar (ControlHandle control, short change) {
/* keep track of the user as he fiddles with the scroll bar */
/* This routine is called while the user has the mouse down. */
/* It makes sure the thumb isn't dragged out-of-bounds. */
short value = GetCtlValue (control), max = GetCtlMax (control);
long newval = value + change; /* this is a long in case we try to go past MAX_INT */
if (newval < 0) newval = 0; else if (newval > max) newval = max;
SetCtlValue (control, (short) newval);
if (newval != value) TEScroll (0, (short) (value - newval) * LINEHEIGHT, hTERec);
}
static pascal void ScrollProc (ControlHandle control, short thePart) {
/* for clicks in the scroll bar or arrows; update the window properly */
short amount;
WindowPtr window;
if (!thePart) return;
window = (*control)->contrlOwner;
switch (thePart) {
case inUpButton: amount = -1; break;
case inDownButton: amount = 1; break;
case inPageUp: amount = -linesInView; break;
case inPageDown: amount = linesInView; break;
}
DoScrollBar (control, amount);
}
static pascal Boolean ScrollClikLoop (void) {
Rect tempRect;
Point mouse;
GrafPtr oldPort;
RgnHandle oldClip;
short amount = 0;
if (FrontWindow () != commandWin) return false;
GetPort (&oldPort);
SetPort (commandWin);
GetClip (oldClip = NewRgn ());
SetRect (&tempRect, INT_MIN, INT_MIN, INT_MAX, INT_MAX);
ClipRect (&tempRect);
GetMouse (&mouse);
if (mouse.v < TEXTREC->viewRect.top) DoScrollBar (vScroll, -1);
else if (mouse.v > TEXTREC->viewRect.bottom) DoScrollBar (vScroll, 1);
SetClip (oldClip);
DisposeRgn (oldClip);
SetPort (oldPort);
return true;
}
static Rect SetTERect (void) {
/* set the dimensions of the text record in its window */
Rect teRect = commandWin->portRect;
teRect.right -= SCROLLER_WIDTH;
InsetRect (&teRect, TEXT_MARGIN, TEXT_MARGIN);
linesInView = (teRect.bottom - teRect.top) / LINEHEIGHT;
teRect.bottom = teRect.top + linesInView * LINEHEIGHT; /* round off */
return teRect;
}
static void SetScrollRect (void) {
/* set the dimensions of the scroll bar in its window */
MoveControl (vScroll, commandWin->portRect.right - SCROLLER_WIDTH, -1);
SizeControl (vScroll, SCROLLER_WIDTH + 1,
(commandWin->portRect.bottom - commandWin->portRect.top) - (SCROLLER_WIDTH - 2));
}
static void AdjustCursor (void) {
/* make the pointer an I-beam iff it's in the text window */
Point mouse = theEvent.where;
if (commandWin != FrontWindow ()) {
SetCursor (&arrow);
return;
} else {
GlobalToLocal (&mouse);
if (PtInRect (mouse, &(TEXTREC->viewRect))) SetCursor (*GetCursor (iBeamCursor));
else SetCursor (&arrow);
}
}
void ShowGrafWin (void) {
/* make the graphics window visible */
ShowWindow (graphicsWin);
SelectWindow (graphicsWin);
SetItem (controlMenu, SHOW_GRAPHICS, "\pHide Graphics");
AdjustCursor ();
graphicsShown = true;
}
void HideGrafWin (void) {
/* hide the graphics window */
HideWindow (graphicsWin);
SetItem (controlMenu, SHOW_GRAPHICS, "\pShow Graphics");
graphicsShown = false;
}
static short roundup (float x) { /* a kludge to round up a float to an int */
if (((int) x) != ((int) (x += 0.5))) x += 0.5;
return (int) x;
}
static void AdjustScrollBar (void) {
/* adjust the scroll bar to match the position of the text view */
short oldval = GetCtlValue (vScroll), oldmax = GetCtlMax (vScroll);
short value, max;
max = TEXTREC->nLines - linesInView;
if ((TEXTREC->teLength > 0) && (*(*TEXTREC->hText + TEXTREC->teLength - 1) == '\r')) max++;
if (max < 0) max = 0;
if (max != oldmax) SetCtlMax (vScroll, max);
value = roundup ((TEXTREC->viewRect.top - TEXTREC->destRect.top) / LINEHEIGHT);
if (value < 0) value = 0; else if (value > max) value = max;
if (value != oldval) SetCtlValue (vScroll, value);
}
static void DrawOnlyGrowIcon (WindowPtr window) { /* doesn't draw scroll bars */
RgnHandle saveRgn;
Rect growRect;
growRect = window->portRect;
growRect.top = growRect.bottom - SCROLLER_WIDTH;
growRect.left = growRect.right - SCROLLER_WIDTH;
GetClip (saveRgn = NewRgn ());
ClipRect (&growRect);
DrawGrowIcon (window);
SetClip (saveRgn);
DisposeRgn (saveRgn);
}
static void UpdateCmdWindow (void) {
long textBottom;
InvalRect (&(commandWin->portRect));
BeginUpdate (commandWin);
EraseRect (&(commandWin->portRect));
FlushOutput ();
DrawOnlyGrowIcon (commandWin);
if (commandWinResized) {
TEXTREC->viewRect = SetTERect ();
TEXTREC->destRect.right = TEXTREC->viewRect.right;
TECalText (hTERec);
SetScrollRect ();
commandWinResized = false;
}
TEXTREC->viewRect = SetTERect (); /* adjust for possible change in height of status line */
textBottom = TEXTREC->destRect.top + (TEXTREC->nLines * LINEHEIGHT);
if (TEXTREC->destRect.top > TEXTREC->viewRect.top)
TEScroll (0, (TEXTREC->viewRect.top - TEXTREC->destRect.top), hTERec);
if (TEXTREC->destRect.top < TEXTREC->viewRect.top) { /* make sure we don't get fractions of lineheights */
int amountOffTheTop = TEXTREC->viewRect.top - TEXTREC->destRect.top;
if (amountOffTheTop % LINEHEIGHT) TEScroll (0, amountOffTheTop % LINEHEIGHT, hTERec);
}
TEUpdate (&(TEXTREC->viewRect), hTERec);
AdjustScrollBar ();
UpdtControl (commandWin, commandWin->visRgn);
EndUpdate (commandWin);
}
void InitMac (void) {
/* do all the necessary initialization mumbo-jumbo */
{ /* set up memory properly */
int i;
if (DefltStack < STACKMIN) SetApplLimit (CurStackBase - STACKMIN);
MaxApplZone ();
for (i = 0; i < MASTERS; i++) MoreMasters ();
}
/* initialize the toolbox */
InitGraf (&thePort);
InitFonts ();
FlushEvents (everyEvent, 0);
InitWindows ();
InitMenus ();
TEInit ();
InitDialogs (NIL);
InitCursor ();
/* see if we have WaitNextEvent and Color Quickdraw */
wneImplemented = (NGetTrapAddress (_WaitNextEvent, ToolTrap) != NGetTrapAddress (_Unimplemented, ToolTrap));
if (NGetTrapAddress ((short) Gestalt, ToolTrap) != NGetTrapAddress (_Unimplemented, ToolTrap)) {
long returnCode;
OSErr err = Gestalt (gestaltQuickdrawVersion, &returnCode);
hasColorQD = ((err == noErr) && (returnCode >= gestalt8BitQD));
} else hasColorQD = false;
{ /* set up menus */
Handle theMenuBar = GetNewMBar (MBAR_RES);
SetMenuBar (theMenuBar);
appleMenu = GetMHandle (APPLE_MENU_RES);
fileMenu = GetMHandle (FILE_MENU_RES);
editMenu = GetMHandle (EDIT_MENU_RES);
controlMenu = GetMHandle (CONTROL_MENU_RES);
AddResMenu (appleMenu, 'DRVR');
DrawMenuBar ();
}
/* get the size of the main screen */
screenWidth = screenBits.bounds.right - screenBits.bounds.left;
screenHeight = screenBits.bounds.bottom - screenBits.bounds.top;
/* create the command and graphics windows */
commandWin = GetNewWindow (CWINRES, &commandWinRec, (WindowPtr) -1L);
if (hasColorQD) graphicsWin = GetNewCWindow (GWINRES, &colorGraphicsWinRec, (WindowPtr) -1L);
else graphicsWin = GetNewWindow (GWINRES, &bwGraphicsWinRec, (WindowPtr) -1L);
SetPort (commandWin);
/* compute the size of the graphics window in split-screen mode */
gHorizontal = SCREEN_MARGIN;
gVertical = MBAR_HEIGHT + TITLEBAR_HEIGHT - 1;
gWidth = screenWidth - (SCREEN_MARGIN * 2);
gHeight = GRAFWIN_HEIGHT;
/* compute the size of the command window in split-screen mode */
sHorizontal = SCREEN_MARGIN;
sVertical = MBAR_HEIGHT + TITLEBAR_HEIGHT - 1 + SCREEN_MARGIN + GRAFWIN_HEIGHT;
sWidth = screenWidth - (SCREEN_MARGIN * 2);
sHeight = screenHeight - MBAR_HEIGHT - TITLEBAR_HEIGHT - (SCREEN_MARGIN * 2) - GRAFWIN_HEIGHT - 1;
/* set up size and drag rects */
dragRect = (*GetGrayRgn ())->rgnBBox;
dragRect.left += DRAG_THRESHOLD;
dragRect.right -= DRAG_THRESHOLD;
dragRect.bottom -= DRAG_THRESHOLD;
sizeRect.top = MIN_WIN_HEIGHT;
sizeRect.left = MIN_WIN_WIDTH;
sizeRect.bottom = screenBits.bounds.bottom - screenBits.bounds.top;
sizeRect.right = screenBits.bounds.right - screenBits.bounds.left;
/* setup the font, size and writing mode for the command window */
TextFont (monaco);
TextSize (9);
TextFace (0);
TextMode (srcCopy);
textStyle[plainStyle].tsFace = 0;
textStyle[boldStyle].tsFace = bold;
currentStyle = plainStyle;
startupTicks = TickCount (); /* take note of what time we're starting up */
{ /* set up scroll bar */
Rect scrollRect;
vScroll = NewControl (commandWin, &scrollRect, "\p", 0, 0, 0, 0, scrollBarProc, NIL);
SetScrollRect ();
ShowControl (vScroll);
}
{ /* set up command text record */
Rect teRect = SetTERect ();
hTERec = TEStylNew (&teRect, &teRect);
TECalText (hTERec);
TEAutoView (true, hTERec);
SetClikLoop (ScrollClikLoop, hTERec);
TEActivate (hTERec);
}
hOutputBuffer = NewHandle (MAX_BUF); /* a handle to a buffer for text to be displayed */
HideGrafWin ();
{ /* see if the user launched the app by opening text files from the Finder */
short doWhat;
CountAppFiles (&doWhat, &howManyFiles);
if (doWhat != appOpen) howManyFiles = 0;
}
UpdateCmdWindow ();
}
static void SetSelection (short start, short end) {
TEXTREC->clikStuff = 255; /* to make sure the caret appears at the start of a line when it should */
/* see tech note "TextEdit EOL Ambiguity" for more information */
TESetSelect (start, end, hTERec);
}
static void CancelFlash (void) {
/* cancel the matching-paren flashing */
if (flashTime) {
flashTime = 0;
SetSelection (cursorBeforeFlash, cursorBeforeFlash);
}
}
static void StopPasting (void) {
/* clean up after finishing a paste */
pastedLength = 0;
if (pastedTextH) {
DisposHandle (pastedTextH);
pastedTextH = NULL;
}
}
static void DoStyle (int whatStyle) {
/* set the text to a certain style */
TESetStyle (doFace, &(textStyle[whatStyle]), false, hTERec);
}
static void FlushOutput (void) {
/* clear out the output buffer, dumping its contents to the window */
short totalLines, scrollAmount, max;
if (outputBufferLength == 0) return;
CancelFlash ();
DoStyle (plainStyle);
HLock (hOutputBuffer);
TEInsert (*hOutputBuffer, outputBufferLength, hTERec);
HUnlock (hOutputBuffer);
outputBufferLength = 0;
if (TEXTREC->teLength > SCROLLBACK_THRESHHOLD) { /* make sure TE record isn't too long */
int i = 1, newLength;
TEPtr textPtr;
while ((TEXTREC->teLength - TEXTREC->lineStarts[i]) > (SCROLLBACK_THRESHHOLD - DELETE_BLOCK)) i++;
i = TEXTREC->lineStarts[i];
newLength = TEXTREC->teLength - i;
textPtr = (TEPtr)(*(TEXTREC->hText));
BlockMove ((Ptr)((long)textPtr + i), textPtr, newLength);
SetHandleSize (TEXTREC->hText, newLength);
TEXTREC->destRect.top += LINEHEIGHT;
TECalText (hTERec);
TEUpdate (&(TEXTREC->viewRect), hTERec);
}
TESelView (hTERec);
AdjustScrollBar ();
}
static void PrepareForInput (void) {
/* get ready to take input */
FlushOutput ();
cmdStart = TEXTREC->selStart;
}
static void DeleteRange (void) {
/* delete the selected range of text, updating cmdStart as necessary */
if (TEXTREC->selEnd <= cmdStart) return;
if (TEXTREC->selStart < cmdStart) SetSelection (cmdStart, TEXTREC->selEnd);
TEDelete (hTERec);
}
static void CopyThisLineToEnd (void) {
/* copy the line the caret is on to the end */
char *buffer;
short b, i, caretOffset;
/* first find out exactly where it starts */
i = TEXTREC->nLines-1; /* first find which line */
while (TEXTREC->selStart < TEXTREC->lineStarts[i]) i--;
while ((i > 0) && ((*(TEXTREC->hText))[TEXTREC->lineStarts[i]-1] != '\r'))
i--; /* for wrapped lines */
i = TEXTREC->lineStarts[i]; /* now zero in on the exact character where it begins */
while ((TEXTCHAR(i) >= '0') && (TEXTCHAR(i) <= '9')) i++; /* skip error level */
if ((TEXTCHAR(i) == '>') && (TEXTCHAR(i+1) == ' ')) i+=2; /* get rid of leading prompt */
caretOffset = TEXTREC->selStart - i; /* how many characters in is the caret? */
/* now put the line into the buffer */
b = 0;
while ((TEXTCHAR(i+b) != '\r') && (i+b < TEXTREC->teLength)) b++; /* find the end of the line */
buffer = (char *) NewPtr (b);
BlockMove (*TEXTREC->hText + i, buffer, b);
buffer[b] = '\0';
/* delete whatever's already on the last line */
SetSelection (cmdStart, TEXTREC->teLength);
TEDelete (hTERec);
DoStyle (boldStyle);
TEInsert (buffer, b, hTERec);
DisposPtr (buffer);
if (caretOffset < 0) caretOffset = b;
SetSelection (cmdStart + caretOffset, cmdStart + caretOffset);
}
static void GoStartOfLine (void) {
short whichLine = TEXTREC->nLines - 1; /* look for the caret; start at the end and go up */
while (TEXTREC->lineStarts[whichLine] > TEXTREC->selStart) whichLine--;
SetSelection (TEXTREC->lineStarts[whichLine], TEXTREC->lineStarts[whichLine]);
AdjustScrollBar ();
}
static void GoEndOfLine (void) {
short whichLine = TEXTREC->nLines - 1; /* look for the caret; start at the end and go up */
while (TEXTREC->lineStarts[whichLine] > TEXTREC->selStart) whichLine--;
if (whichLine == TEXTREC->nLines - 1)
SetSelection (TEXTREC->teLength, TEXTREC->teLength);
else SetSelection (TEXTREC->lineStarts[whichLine+1] - 1, TEXTREC->lineStarts[whichLine+1] - 1);
AdjustScrollBar ();
}
static void GoBackOneWord (void) {
short i = TEXTREC->selStart;
while ((i > 0) && !isalnum (TEXTCHAR(i-1))) i--;
while ((i > 0) && isalnum (TEXTCHAR(i-1))) i--;
SetSelection (i, i);
}
static void GoForwardOneWord (void) {
short i = TEXTREC->selStart;
while ((i < TEXTREC->teLength) && !isalnum (TEXTCHAR(i))) i++;
while ((i < TEXTREC->teLength) && isalnum (TEXTCHAR(i))) i++;
SetSelection (i, i);
}
static void EditFreely (void) {
Boolean done;
do {
done = false;
DoEvent ();
if (pastedLength > 0) { /* if there is still text to paste, paste it */
int i = 0;
CancelFlash ();
if (TEXTREC->selStart < cmdStart) StopPasting ();
else {
while ((i < pastedLength) && (((char *)(*pastedTextH))[i] != '\r')) i++;
DoStyle (boldStyle);
TEInsert (*pastedTextH, i, hTERec);
AdjustScrollBar ();
if (i < pastedLength) { /* we were stopped by a carriage return, so eat it */
i++;
done = true;
}
pastedLength -= i;
if (pastedLength > 0) {
BlockMove ((Ptr)((long)(*pastedTextH) + i), *pastedTextH, pastedLength);
SetHandleSize (pastedTextH, pastedLength);
} else StopPasting ();
}
}
else if (recentChar) { /* if the last event got us a character, process it */
int i;
Boolean wasOnLastLine;
CancelFlash ();
if ((TEXTREC->selEnd <= cmdStart) && (TEXTREC->selStart != TEXTREC->selEnd)) continue;
if (TEXTREC->selStart < cmdStart) SetSelection (cmdStart, TEXTREC->selEnd);
wasOnLastLine = (TEXTREC->selStart >= cmdStart);
if ((recentChar & 0xfc) == 0x1c) { /* was this an arrow key? */
TEXTREC->clikStuff = 255; /* to make sure the caret appears where it should */
TEKey (recentChar, hTERec);
AdjustScrollBar ();
continue;
}
if (!wasOnLastLine) CopyThisLineToEnd ();
switch (recentChar) {
case FWDDEL:
if (TEXTREC->selStart != TEXTREC->selEnd) DeleteRange ();
else if ((TEXTREC->selStart >= cmdStart) && (TEXTREC->selStart < TEXTREC->teLength)) {
TEDeactivate (hTERec);
SetSelection (TEXTREC->selStart, TEXTREC->selStart + 1);
TEDelete (hTERec);
if (FrontWindow () == commandWin) TEActivate (hTERec);
}
break;
case CLRKEY:
if (TEXTREC->selStart != TEXTREC->selEnd) DeleteRange ();
break;
case DELETE:
if (TEXTREC->selStart != TEXTREC->selEnd) DeleteRange ();
else if (TEXTREC->selStart > cmdStart) {
TEXTREC->clikStuff = 255; /* to make sure the caret appears where it should */
TEKey (DELETE, hTERec);
}
break;
case RETURN:
if (wasOnLastLine) done = true;
break;
case ENTER: /* ENTER ends command no matter what */
done = true;
break;
default:
DoStyle (boldStyle);
TEXTREC->clikStuff = 255; /* to make sure the caret appears where it should */
TEKey (recentChar, hTERec);
if ((recentChar == ')') && (TEXTREC->selStart > cmdStart)) {
short parenCount = -1;
Boolean inQuotes = false;
i = TEXTREC->selStart - 1;
while ((--i >= cmdStart) && (parenCount != 0))
switch ((*TEXTREC->hText)[i]) {
case DBLQUOTE: inQuotes = !inQuotes; break;
case '(': if (!inQuotes) parenCount++; break;
case ')': if (!inQuotes) parenCount--; break;
}
if (parenCount == 0) {
cursorBeforeFlash = TEXTREC->selStart;
SetSelection (i+1, i+2); /* flash the matching open-paren */
flashTime = 100;
}
} else if ((recentChar == DBLQUOTE) && (TEXTREC->selStart > cmdStart)) {
i = TEXTREC->selStart - 1;
while ((--i >= cmdStart) && ((*TEXTREC->hText)[i] != DBLQUOTE)) ;
if ((*TEXTREC->hText)[i] == DBLQUOTE) {
cursorBeforeFlash = TEXTREC->selStart;
SetSelection (i, i+1); /* flash the matching double-quote */
flashTime = 100;
}
}
}
AdjustScrollBar ();
}
} while (!done);
}
char *macgets (void) {
/* retrieve a typed character */
/* Note that this uses some extensive (and clever, if I may say so myself) buffering. */
int i, b, bufSize;
char *ptr, *buffer;
Boolean done, onLastLine;
PrepareForInput ();
do { /* repeat until a full expression has been typed */
EditFreely (); /* allow free editing for a while */
/* Now, we have a complete command to parse, if and only if: */
/* - the cursor was on the last line when the user pressed Return or Enter, and */
/* - the user either pressed Enter, or else every '(' since the beginning */
/* of the command is matched by a ')'. */
/* Quoting is watched for. ( ") is not a complete expression. */
done = true;
if (TEXTREC->selStart != TEXTREC->teLength) /* if we're not at the end already */
SetSelection (TEXTREC->teLength, TEXTREC->teLength); /* send cursor to end */
TEXTREC->clikStuff = 255; /* to make sure the caret appears where it should */
TEKey ('\r', hTERec);
/* check and see if we've completed the command yet */
if (recentChar != ENTER) {
Boolean inQuotes = false;
short parenCount = 0;
for (i = cmdStart; i < TEXTREC->teLength; i++)
switch ((*TEXTREC->hText)[i]) {
case DBLQUOTE: inQuotes = !inQuotes; break;
case '(': if (!inQuotes) parenCount++; break;
case ')': if (!inQuotes) parenCount--; break;
}
if ((parenCount > 0) || inQuotes) done = false;
}
AdjustScrollBar ();
} while (!done);
/* put the entire command into the buffer, and return it */
bufSize = TEXTREC->teLength - cmdStart;
buffer = (char *) NewPtr (bufSize + 1);
BlockMove (*TEXTREC->hText + cmdStart, buffer, bufSize);
buffer[bufSize] = '\0';
return buffer;
}
void macputc (int ch) {
/* put a char into the output buffer, and flush the buffer if necessary */
switch (ch) {
case '\t':
do { macputc (' '); } while (cursorPos & 7);
break;
case DELETE:
if (cursorPos) cursorPos--; /* and fall through to default */
default:
if (outputBufferLength == MAX_BUF) FlushOutput ();
if (ch == '\n') {
cursorPos = 0;
(*hOutputBuffer)[outputBufferLength++] = '\r';
} else {
cursorPos++;
(*hOutputBuffer)[outputBufferLength++] = ch;
}
}
}
void macputs (char *s) {
/* for completeness */
while (*s) macputc (*s++);
}
void scrflush (void) {
extern void osflush (void);
/* clear out everything */
FlushOutput ();
osflush ();
}
void scrclear (void) {
/* clear text window -- not implemented */
}
static void DoAppleMenu (int theItem) {
switch (theItem) {
case ABOUT_ITEM:
DoAboutBox ();
break;
default: {
Str255 name;
GetItem (appleMenu, theItem, name);
OpenDeskAcc (name);
break;
}
}
}
static void DoFileMenu (int theItem) {
extern xlload (char *, int, int);
extern wrapup (void);
SFReply theFile;
SFTypeList fileTypes;
Point pt = { 100, 100 };
fileTypes[0] = 'TEXT';
switch (theItem) {
case LOAD:
case LOAD_NOISILY:
StopPasting ();
SFGetFile (pt, NIL, NIL, 1, fileTypes, NIL, &theFile);
/* EraseBottomScroller (true); /* SFGetFile puts it there */
if (theFile.good) {
Str255 theFullPath;
HiliteMenu (0);
SetVol (NIL, theFile.vRefNum);
SetSelection (TEXTREC->teLength, TEXTREC->teLength); /* send cursor to end */
if ((xlload (PtoCstr (theFile.fName), 1, (theItem == LOAD_NOISILY))) == 0)
xlabort ("load error");
macputs ("> ");
PrepareForInput ();
}
break;
case QUIT:
wrapup ();
}
}
static void DoEditMenu (int theItem) {
if (SystemEdit (theItem-1) == false)
switch (theItem) {
case CUT: case COPY:
if (ZeroScrap () == noErr) {
TECopy (hTERec); /* after copying, export the TE scrap */
if (TEToScrap () != noErr) ZeroScrap ();
}
if (theItem == CUT) DeleteRange ();
break;
case PASTE: {
long scrapOffset;
if (pastedTextH) DisposHandle (pastedTextH);
pastedTextH = (CharsHandle) NewHandle (0);
pastedLength = GetScrap (pastedTextH, 'TEXT', &scrapOffset);
if (pastedLength < 0) pastedLength = 0; /* error */
else {
SetHandleSize (pastedTextH, pastedLength + 1);
HLock (pastedTextH);
((char *)(*pastedTextH))[pastedLength] = '\0';
HUnlock (pastedTextH);
}
} /* and fall through ... */
case CLEAR:
DeleteRange ();
break;
}
}
static void DoControlMenu (int theItem) {
extern xlbreak (char *, char *);
extern char *s_unbound;
extern xlcontinue (void);
extern xlcleanup (void);
extern xlabort (char *);
extern xltoplevel (void);
scrflush ();
HiliteMenu (0);
switch (theItem) {
case BREAK: StopPasting (); xlbreak ("user break", s_unbound); PrepareForInput (); break;
case CONTINUE: StopPasting (); xlcontinue (); PrepareForInput (); break;
case CLEAN_UP: StopPasting (); xlcleanup (); PrepareForInput (); break;
case CANCEL_INPUT: StopPasting (); xlabort ("input canceled"); PrepareForInput (); break;
case TOP_LEVEL: StopPasting (); xltoplevel (); PrepareForInput (); break;
case SHOW_GRAPHICS:
if (graphicsShown) HideGrafWin ();
else ShowGrafWin ();
break;
case SPLIT_SCREEN:
MoveWindow (commandWin, sHorizontal, sVertical, -1);
SizeWindow (commandWin, sWidth, sHeight, -1);
InvalRect (&commandWin->portRect);
SetTERect ();
SetScrollRect ();
ShowGrafWin ();
MoveWindow (graphicsWin, gHorizontal, gVertical, -1);
SizeWindow (graphicsWin, gWidth, gHeight, -1);
break;
}
}
static void DoMenu (long choice) {
int theMenu = HiWord (choice), theItem = LoWord (choice);
HiliteMenu (theMenu);
switch (theMenu) {
case APPLE_MENU_RES: DoAppleMenu (theItem); break;
case FILE_MENU_RES: DoFileMenu (theItem); break;
case EDIT_MENU_RES: DoEditMenu (theItem); break;
case CONTROL_MENU_RES: DoControlMenu (theItem); break;
}
HiliteMenu (0);
}
static void AdjustMenus (void) {
/* turn the stuff in the Edit menu on and off as necessary */
long temp;
DisableItem (editMenu, UNDO);
if (TEXTREC->selStart != TEXTREC->selEnd) {
EnableItem (editMenu, CUT);
EnableItem (editMenu, COPY);
EnableItem (editMenu, CLEAR);
} else {
DisableItem (editMenu, CUT);
DisableItem (editMenu, COPY);
DisableItem (editMenu, CLEAR);
}
if (GetScrap (NIL, 'TEXT', &temp) > 0) EnableItem (editMenu, PASTE);
else DisableItem (editMenu, PASTE);
}
static void DoContent (void) {
/* handle a click in a window's content region */
ControlHandle theScrollBar;
GrafPtr oldPort;
int scrollValue;
Point mouse = theEvent.where;
int thePart;
GetPort (&oldPort);
SetPort (commandWin);
GlobalToLocal (&mouse);
if (thePart = FindControl (mouse, commandWin, &theScrollBar))
switch (thePart) {
case inUpButton:
case inDownButton:
case inPageUp:
case inPageDown:
scrollValue = TrackControl (theScrollBar, mouse, (ProcPtr) ScrollProc);
break;
case inThumb:
scrollValue = GetCtlValue (theScrollBar);
thePart = TrackControl (theScrollBar, mouse, NIL);
if (thePart) {
scrollValue -= GetCtlValue (theScrollBar);
if (scrollValue) TEScroll (0, scrollValue * LINEHEIGHT, hTERec);
}
break;
}
else if (PtInRect (mouse, &(TEXTREC->viewRect)))
TEClick (mouse, (theEvent.modifiers & shiftKey) != 0, hTERec);
SetPort (oldPort);
}
static void DoMouseDown (void) {
WindowPtr whichWindow;
short int thePart = FindWindow (theEvent.where, &whichWindow);
switch (thePart) {
case inSysWindow:
SystemClick (&theEvent, whichWindow);
break;
case inDrag:
DragWindow (whichWindow, theEvent.where, &dragRect);
break;
case inMenuBar: {
long choice;
AdjustMenus ();
choice = MenuSelect (theEvent.where);
if (choice) DoMenu (choice);
break;
}
case inGoAway:
if ((whichWindow == graphicsWin)
&& (TrackGoAway (whichWindow, theEvent.where)))
HideGrafWin ();
break;
case inContent:
if ((FrontWindow () == commandWin) && (whichWindow == commandWin))
DoContent ();
else SelectWindow (whichWindow);
break;
case inGrow:
case inZoomIn:
case inZoomOut: {
long newSize;
GrafPtr oldPort;
if (thePart == inGrow) newSize = GrowWindow (whichWindow, theEvent.where, &sizeRect);
if (((thePart == inGrow) && newSize)
|| ((thePart != inGrow) && TrackBox (whichWindow, theEvent.where, thePart))) {
GetPort (&oldPort);
SetPort (whichWindow);
EraseRect (&whichWindow->portRect);
if (thePart == inGrow) SizeWindow (whichWindow, LoWord (newSize), HiWord (newSize), -1);
else ZoomWindow (whichWindow, thePart, 0);
commandWinResized = true;
InvalRect (&whichWindow->portRect);
SetPort (oldPort);
}
break;
}
}
}
static void DoKeyPress (void) {
short whatKey = theEvent.message & charCodeMask;
if (theEvent.modifiers & cmdKey) {
long choice;
AdjustMenus ();
if (choice = MenuKey (theEvent.message)) DoMenu (choice);
else if (((whatKey == 'w') || (whatKey == 'W')) && (FrontWindow () == graphicsWin))
HideGrafWin ();
else if (whatKey == LEFTARROW) GoStartOfLine ();
else if (whatKey == RIGHTARROW) GoEndOfLine ();
else if (whatKey == UPARROW) DoScrollBar (vScroll, -linesInView);
else if (whatKey == DOWNARROW) DoScrollBar (vScroll, linesInView);
}
else if (theEvent.modifiers & optionKey) {
if (whatKey == LEFTARROW) GoBackOneWord ();
else if (whatKey == RIGHTARROW) GoForwardOneWord ();
}
else switch (whatKey) {
case PAGEUP: DoScrollBar (vScroll, -linesInView); break;
case PAGEDN: DoScrollBar (vScroll, linesInView); break;
case HOMEKEY: DoScrollBar (vScroll, INT_MIN); break;
case ENDKEY: DoScrollBar (vScroll, INT_MAX); break;
case FNKEY: break;
case HELPKEY: break;
default: recentChar = theEvent.message & charCodeMask;
}
}
void DoEvent (void) {
if (wneImplemented) WaitNextEvent (everyEvent, &theEvent, NIL, NIL);
else {
SystemTask ();
GetNextEvent (everyEvent, &theEvent);
}
AdjustCursor ();
if ((flashTime) && (--flashTime == 0)) SetSelection (cursorBeforeFlash, cursorBeforeFlash);
if (outputBufferLength) FlushOutput ();
if (FrontWindow () == commandWin) TEIdle (hTERec);
recentChar = '\0';
if (howManyFiles) {
extern xlload (char *, int, int);
AppFile aFile;
GetAppFiles (++whichFile, &aFile);
if (whichFile == howManyFiles) {
howManyFiles = 0;
whichFile = 0;
}
SetVol (NIL, aFile.vRefNum);
PtoCstr (aFile.fName);
if (xlload ((char *) aFile.fName, 1, 0) == 0) xlabort ("load error");
ClrAppFiles (whichFile);
if (howManyFiles == 0) {
macputs ("> ");
PrepareForInput ();
}
}
switch (theEvent.what) {
case mouseDown:
DoMouseDown ();
break;
case keyDown:
case autoKey:
DoKeyPress ();
break;
case activateEvt: {
WindowPtr whichWindow = (WindowPtr)theEvent.message;
SetPort (whichWindow);
if (whichWindow == commandWin) {
DrawOnlyGrowIcon (commandWin);
if ((theEvent.modifiers & activeFlag) == 1) {
TEActivate (hTERec);
HiliteControl (vScroll, 0);
} else {
TEDeactivate (hTERec);
HiliteControl (vScroll, 255);
}
}
break;
}
case updateEvt: {
if ((WindowPtr)theEvent.message == commandWin) UpdateCmdWindow ();
break;
}
}
}
void MacWrapUp (void) {
/* take everything down in preparation for quitting */
StopPasting ();
CloseWindow (graphicsWin);
CloseWindow (commandWin);
TEDispose (hTERec);
DisposHandle (hOutputBuffer);
}